using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Diagnostics;

namespace ASPNetAjaxInstaller
{
    public class InstallFeature : SPFeatureReceiver
    {
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            try
            {

                SPWebApplication curWeb = (SPWebApplication)properties.Feature.Parent;

                if (curWeb != null)
                {
                    foreach (ModificationEntry entry in GetModifications())
                    {
                        curWeb.WebConfigModifications.Add(CreateModification(entry));
                    }

                    curWeb.Update();
                    curWeb.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();

                }

            }
            catch (Exception err)
            {
                if (!EventLog.SourceExists("AJAX"))
                {
                    EventLog.CreateEventSource("AJAX", "Application");
                }
                EventLog.WriteEntry("AJAX", "Error: " + err.Message);
            }
        }

        /// <summary>
        /// Takes our custom ModificationEntry struct and applies it to a SPWebConfigModification type
        /// </summary>
        /// <param name="modEntry"></param>
        /// <returns></returns>
        public static SPWebConfigModification CreateModification(ModificationEntry modEntry)
        {
            SPWebConfigModification modification = new SPWebConfigModification(modEntry.Name, modEntry.Path);
            modification.Owner = "AJAXInstaller";
            modification.Sequence = 0;
            modification.Type = modEntry.ModType;
            modification.Value = modEntry.Value;
            return modification;
        }

        public List<ModificationEntry> GetModifications()
        {

            List<ModificationEntry> list = new List<ModificationEntry>();

            ModificationEntry item = new ModificationEntry();
            item.Name = "sectionGroup[@name='system.web.extensions']";
            item.Path = "configuration/configSections";
            item.Value = "<sectionGroup name=\"system.web.extensions\" type=\"System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\"><sectionGroup name=\"scripting\" type=\"System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\"><section name=\"scriptResourceHandler\" type=\"System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" requirePermission=\"false\" allowDefinition=\"MachineToApplication\"/><sectionGroup name=\"webServices\" type=\"System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\"><section name=\"jsonSerialization\" type=\"System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" requirePermission=\"false\" allowDefinition=\"Everywhere\" /><section name=\"profileServic\" type=\"System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" requirePermission=\"false\" allowDefinition=\"MachineToApplication\" /><section name=\"authenticationService\" type=\"System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" requirePermission=\"false\" allowDefinition=\"MachineToApplication\" /></sectionGroup></sectionGroup></sectionGroup>";
            item.ModType = 0;
            list.Add(item);

            ModificationEntry entry2 = new ModificationEntry();
            entry2.Name = "add[@assembly='System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35']";
            entry2.Path = "configuration/system.web/compilation/assemblies";
            entry2.Value = "<add assembly=\"System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\"/>";
            entry2.ModType = 0;
            list.Add(entry2);

            ModificationEntry entry3 = new ModificationEntry();
            entry3.Name = "add[@path='*.asmx']";
            entry3.Path = "configuration/system.web/httpHandlers";
            entry3.Value = "<add verb=\"*\" path=\"*.asmx\" validate=\"false\" type=\"System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\"/>";
            entry3.ModType = 0;
            list.Add(entry3);

            ModificationEntry entry4 = new ModificationEntry();
            entry4.Name = "add[@path='*_AppService.axd']";
            entry4.Path = "configuration/system.web/httpHandlers";
            entry4.Value = "<add verb=\"*\" path=\"*_AppService.axd\" validate=\"false\" type=\"System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\"/>";
            entry4.ModType = 0;
            list.Add(entry4);

            ModificationEntry entry5 = new ModificationEntry();
            entry5.Name = "add[@path='ScriptResource.axd']";
            entry5.Path = "configuration/system.web/httpHandlers";
            entry5.Value = "<add verb=\"GET,HEAD\" path=\"ScriptResource.axd\" type=\"System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" validate=\"false\"/>";
            entry5.ModType = 0;
            list.Add(entry5);

            ModificationEntry entry6 = new ModificationEntry();
            entry6.Name = "add[@name='ScriptModule']";
            entry6.Path = "configuration/system.web/httpModules";
            entry6.Value = "<add name=\"ScriptModule\" type=\"System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\"/>";
            entry6.ModType = 0;
            list.Add(entry6);

            ModificationEntry entry7 = new ModificationEntry();
            entry7.Name = "SafeControl[@Namespace='System.Web.UI']";
            entry7.Path = "configuration/SharePoint/SafeControls";
            entry7.Value = "<SafeControl Assembly=\"System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" Namespace=\"System.Web.UI\" TypeName=\"*\" Safe=\"True\" />";
            entry7.ModType = 0;
            list.Add(entry7);

            ModificationEntry entry8 = new ModificationEntry();
            entry8.Name = "system.web.extensions";
            entry8.Path = "configuration";
            entry8.Value = "<system.web.extensions><scripting><webServices><!-- Uncomment this line to enable the authentication service. Include requireSSL=\"true\" if appropriate. --><!--<authenticationService enabled=\"true\" requireSSL = \"true|false\"/>--><!-- Uncomment these lines to enable the profile service. To allow profile properties to be retrieved and modified in ASP.NET AJAX applications, you need to add each property name to the readAccessProperties and writeAccessProperties attributes. --><!--<profileService enabled=\"true\"readAccessProperties=\"propertyname1,propertyname2\"writeAccessProperties=\"propertyname1,propertyname2\" />--></webServices><!--<scriptResourceHandler enableCompression=\"true\" enableCaching=\"true\" />--></scripting></system.web.extensions>";
            entry8.ModType = 0;
            list.Add(entry8);

            ModificationEntry entry9 = new ModificationEntry();
            entry9.Name = "system.webServer";
            entry9.Path = "configuration";
            entry9.Value = "<system.webServer><validation validateIntegratedModeConfiguration=\"false\"/><modules><add name=\"ScriptModule\" preCondition=\"integratedMode\" type=\"System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\"/></modules><handlers><remove name=\"WebServiceHandlerFactory-Integrated\" /><add name=\"ScriptHandlerFactory\" verb=\"*\" path=\"*.asmx\" preCondition=\"integratedMode\" type=\"System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\"/><add name=\"ScriptHandlerFactoryAppServices\" verb=\"*\" path=\"*_AppService.axd\" preCondition=\"integratedMode\" type=\"System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\"/><add name=\"ScriptResource\" preCondition=\"integratedMode\" verb=\"GET,HEAD\" path=\"ScriptResource.axd\" type=\"System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" /></handlers></system.webServer>";
            entry9.ModType = 0;
            list.Add(entry9);

            ModificationEntry entry10 = new ModificationEntry();
            entry10.Name = "pages.controls";
            entry10.Path = "configuration/system.web/pages";
            entry10.Value = "<controls>" + "<add tagPrefix=\"asp\" namespace=\"System.Web.UI\" assembly=\"System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" />" + "</controls>";
            entry10.ModType = 0;
            list.Add(entry10);

            /*ModificationEntry entry12 = new ModificationEntry();
            entry12.Name = "asp.tagprefix";
            entry12.Path = "configuration/system.web/pages/controls";
            entry12.Value = "<add tagPrefix=\"asp\" namespace=\"System.Web.UI\" assembly=\"System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" />";
            entry12.ModType = 0;

            list.Add(entry12);*/
            

            return list;

        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            try
            {

                SPWebApplication curWeb = (SPWebApplication)properties.Feature.Parent;

                if (curWeb != null)
                {

                    foreach (ModificationEntry entry in GetModifications())
                    {
                        curWeb.WebConfigModifications.Remove(CreateModification(entry));
                    }

                    
                    curWeb.Update();
                    curWeb.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();

                }

            }
            catch (Exception err)
            {
                if (!EventLog.SourceExists("AJAX"))
                {
                    EventLog.CreateEventSource("AJAX", "Application");
                }
                EventLog.WriteEntry("AJAX", "Error (Deactivating) : " + err.Message);
            }
        }

        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
            
        }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
            
        }
    }

    /// <summary>
    /// Encapsulates a web.config entry
    /// </summary>
    public struct ModificationEntry
    {
        public string Name;
        public string Path;
        public string Value;
        public SPWebConfigModification.SPWebConfigModificationType ModType;

        public ModificationEntry(string name, string path, string value, SPWebConfigModification.SPWebConfigModificationType modType)
        {
            this.Name = name;
            this.Path = path;
            this.ModType = modType;
            this.Value = value;
        }
    }
}
